using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace pong1
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// This class performs physics calculations for colliding bodies 
    /// </summary>
    public class Physics : Microsoft.Xna.Framework.GameComponent
    {
        String strEventReceiver;        // Event receiver name of Physics class
        EventCollection eventCollection;    // Stores reference to pending events list
        String[] eventsForThisGameObjectArray;  // Stores a list of events that this object polls for
        
        public Physics(Game game)
            : base(game)
        {
            strEventReceiver = "physics"; 
            eventCollection = (EventCollection)Game.Services.GetService(typeof(EventCollection));
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            eventCollection.RegisterForEvent("updatetrajectory", strEventReceiver);    // Ball sends update trajectory message to Physics at every collision 
            String eventsForThisObject;
            eventsForThisObject = eventCollection.GetEventsForReceiver(strEventReceiver);
            eventsForThisGameObjectArray = eventsForThisObject.Split(',');
            
            //eventCollection.RegisterForEvent("paddle2velocity", strEventReceiver); // Register for paddle and ball velocities for calculating collision velocity of ball
            //eventCollection.RegisterForEvent("ballvelocity", strEventReceiver);     
            base.Initialize();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // Process events for Physics. 
            if (!eventCollection.IsEmpty())
            {
                Event e;
                for (int j = 0; j < eventsForThisGameObjectArray.Length; j++)       // For each event this paddle is listening for, retrieve and process the event
                {
                    e = eventCollection.RetrieveEvent(eventsForThisGameObjectArray[j]); 

                    if (e != null)
                    {
                        processEvent(e);
                    }
                }

            }

            base.Update(gameTime);
        }

        /// <summary>
        /// The event processor for all events handled by Physics
        /// </summary>
        /// <param name="e"></param>
        private void processEvent(Event e)
        {

            switch (e.EventName)
            {
                case "updatetrajectory":
                    int X = Convert.ToInt32(e.EventArguments[0].ArgumentValue);     // Store the X and Y coordinates of the ball
                    int Y = Convert.ToInt32(e.EventArguments[1].ArgumentValue);
                    float velocityx = float.Parse(e.EventArguments[2].ArgumentValue);
                    float velocityy = float.Parse(e.EventArguments[3].ArgumentValue);

                    float m = velocityy / velocityx;        // Calculate gradient
                    int screenX = 0, screenY = 0, c = 0;

                    if (velocityx < 0)  // -ve velocity means ball is travelling towards left side of screen
                    {
                        // Solve for intersection between two lines: x = 0, and y = m*x + c
                         
                        c = Y - (int)(m * X);
                        screenY = (int)(m * screenX) + c;
                    }
                    else 
                    {
                        screenX = Convert.ToInt32(e.EventArguments[4].ArgumentValue); // The screen width
                        screenY = 0;
                        c = 0;
                        // Solve for intersection between two lines: x = GraphicsDevice.Viewport.Width , and y = m*x + c
                         
                        c = Y - (int)(m * X);
                        screenY = (int)(m * screenX) + c;
                    
                    }
                    eventCollection.RetrieveEvent("balltrajectory");
                    Event e1 = new Event();
                    e1.EventName = "balltrajectory";
                    e1.EventArguments[0].ArgumentName = "x";
                    e1.EventArguments[0].ArgumentType = "int";
                    e1.EventArguments[0].ArgumentValue = screenX.ToString();

                    e1.EventArguments[1].ArgumentName  = "y";
                    e1.EventArguments[1].ArgumentType = "int";
                    e1.EventArguments[1].ArgumentValue = screenY.ToString();

                    eventCollection.Add(e1);
                    break;
                default:
                    break;
            }
        }

    }
}
